package com.ruoyi.web.controller.common;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.config.AliYunOSSConfig;
import com.ruoyi.system.service.impl.SysUserServiceImpl;
import com.ruoyi.web.dto.FileUploadDTO;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;

@RestController
public class FileController {

    @Autowired
    private AliYunOSSConfig aliYunOSSConfig;
    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);


    @RequestMapping("/common/file/upload")
    //@Log(title = "图片上传")
    public Object upload(@RequestParam("file") MultipartFile file,@RequestParam String type) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(aliYunOSSConfig.getEndpoint(), aliYunOSSConfig.getAccessKeyId(), aliYunOSSConfig.getAccessKeySecret());
        //文件新路径
        String fileName = file.getOriginalFilename();
        String filePath = getFilePath(type,fileName);
        try {
            // 图片压缩
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            Thumbnails.of(file.getInputStream())
                    .scale(0.5f)
                    .toOutputStream(outputStream);
            byte[] bytes = outputStream.toByteArray();
            InputStream inputStream = new ByteArrayInputStream(bytes);
            MultipartFile multipartFile = getMultipartFile(inputStream, file.getOriginalFilename());
            // 上传至oss
            PutObjectRequest putObjectRequest = new PutObjectRequest(aliYunOSSConfig.getBucketName(), filePath, new ByteArrayInputStream(multipartFile.getBytes()));
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);
            putObjectRequest.setMetadata(metadata);
            ossClient.putObject(putObjectRequest);
            ossClient.shutdown();
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("上传失败");
        }

        FileUploadDTO fileUploadDTO = new FileUploadDTO();
        fileUploadDTO.setUrl(aliYunOSSConfig.getUrlPrefix()+"/"+filePath);
        return AjaxResult.success(fileUploadDTO);
    }

    @RequestMapping("/mobile/common/file/upload")
    //@Log(title = "图片上传")
    public Object mobileupload(@RequestParam("file") MultipartFile file,@RequestParam String type) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(aliYunOSSConfig.getEndpoint(), aliYunOSSConfig.getAccessKeyId(), aliYunOSSConfig.getAccessKeySecret());
        //文件新路径
        String fileName = file.getOriginalFilename();
        String filePath = getFilePath(type,fileName);
        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(aliYunOSSConfig.getBucketName(), filePath, new ByteArrayInputStream(file.getBytes()));

            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);
            putObjectRequest.setMetadata(metadata);

            ossClient.putObject(putObjectRequest);
            ossClient.shutdown();
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("上传失败");
        }

        FileUploadDTO fileUploadDTO = new FileUploadDTO();
        fileUploadDTO.setUrl(aliYunOSSConfig.getUrlPrefix()+"/"+filePath);
        return AjaxResult.success(fileUploadDTO);
    }

    private static String getFilePath(String type,String sourceFileName) {
        return type+"/"+ System.currentTimeMillis() +
                RandomUtils.nextInt(100, 9999) + "." +
                StringUtils.substringAfterLast(sourceFileName, ".");
    }

    /**
     * 获取封装得MultipartFile
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return MultipartFile
     */
    public MultipartFile getMultipartFile(InputStream inputStream, String fileName) {
        FileItem fileItem = createFileItem(inputStream, fileName);
        //CommonsMultipartFile是feign对multipartFile的封装，但是要FileItem类对象
        return new CommonsMultipartFile(fileItem);
    }

    /**
     * FileItem类对象创建
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return FileItem
     */
    public FileItem createFileItem(InputStream inputStream, String fileName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "file";
        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        OutputStream os = null;
        //使用输出流输出输入流的字节
        try {
            os = item.getOutputStream();
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            inputStream.close();
        } catch (IOException e) {
            log.error("Stream copy exception", e);
            throw new IllegalArgumentException("文件上传失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);

                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);
                }
            }
        }

        return item;
    }

}
